  const devIP_addr = '192.168.1.211';
// const devIP_addr = '127.0.0.1';
const devIP_port = '5211';
const jxSystemInfo_Sql = Buffer.from('select * from CfgTab_devInfo', 'utf-8');
const jxDevData_Sql = Buffer.from('select * from jxDevData', 'utf-8');
const CfgTab_mbPoll_Sql = Buffer.from('select * from CfgTab_mbPoll', 'utf-8');
const jxDevID_Sql = Buffer.from('select * from jxSensorId', 'utf-8');
const CfgTab_IO_DI_Sql = Buffer.from('select * from CfgTab_IO_DI', 'utf-8');
const CfgTab_IO_DO_Sql = Buffer.from('select * from CfgTab_IO_DO', 'utf-8');
const CfgTab_RS485_Sql = Buffer.from('select * from CfgTab_RS485', 'utf-8');
const CfgTab_nonStdMbCmd_Sql = Buffer.from('select * from CfgTab_nonStdMbCmd', 'utf-8');
const jxLinkageTab_Sql = Buffer.from('select * from jxLinkageTab', 'utf-8');


var g_commTimeoutCnt = 0;

var udpRdData = [
  jxSystemInfo_Sql,
  jxDevData_Sql,
  CfgTab_mbPoll_Sql,
  jxDevID_Sql,
  CfgTab_IO_DI_Sql,
  CfgTab_IO_DO_Sql,
  CfgTab_RS485_Sql,
  CfgTab_nonStdMbCmd_Sql,
  jxLinkageTab_Sql,
];
var devTabData = new Array();
var devRealData = new Array();

var tabName = [
  'CfgTab_devInfo',
  'jxDevData',
  'CfgTab_mbPoll',
  'jxSensorId',
  'CfgTab_IO_DI',
  'CfgTab_IO_DO',
  'CfgTab_RS485',
  'CfgTab_nonStdMbCmd',
  'jxLinkageTab',
];

function getDevTabData(msg) {
  if (msg === 'all') {
    return devTabData;
  }
  for (let i = 0; i < tabName.length; i++) {
    if (msg === tabName[i]) {
      return devTabData[i];
    }
  }
  return null;
}
function getDevRealData() {
  return devRealData;
}

function getDevRealDataComPacketSent() {

  let data = new dev_formPacket2Sent(0x80, null);
  udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
  
}
var g_packetNum = 0x0;

const dgram = require('dgram');
const udpserver = dgram.createSocket('udp4');

udpserver.on('error', err => {
  console.log(`udpserverr error:\n${err.stack}`);
  udpserver.close();
});

udpserver.on('message', (msg, rinfo) => {
//  console.log(msg);
  let calCrc = crcCheck(msg, 3, msg.length - 6);
  let recvCrc = msg.readUInt16BE(msg.length - 3);

  if (calCrc != recvCrc) {
    console.log(`Crc err`);
    console.log(`calCrc` + calCrc);
    console.log(`recvCrc` + recvCrc);
  } else {
    let recvPacketNum = msg.readUInt16LE(3);
    let recvCmd = msg.readUInt8(10);
    let recvAnswer = msg.readUInt8(11);

    if (recvCmd === 0x81 && recvPacketNum === get_packeIdx && recvAnswer === 0) {
      let row = msg.readUInt16LE(12);
      let col = msg.readUInt16LE(14);
      get_packeIdx++;
      timeOver = countTime;

      var colArray = new Array();
      var rowArray = new Array();
      var index = 16;
      //console.log(`row=` + row + ' col=' + col);
      // rowArray.push(tabName[recvPacketNum]);
      // rowArray.push(row);
      // rowArray.push(col);
      for (let i = 0; i < row + 1; i++) {
        for (let j = 0; j < col; j++) {
          let len = 0;
          for (let m = 0; m < msg.length; m++) {
            if (msg[index + m] == 0) break;
            len++;
          }
          let myArray = [];
          for (let n = 0; n < len; n++) {
            myArray[n] = msg[index + n];
          }
          colArray.push(Utf8ArrayToStr(myArray));
          index = index + len + 1;
        }
        rowArray.push(colArray);
        colArray = [];
      }
      devTabData[recvPacketNum] = rowArray;
      // console.log(devTabData[recvPacketNum]);
    } else if (recvCmd === 0x80 && recvAnswer === 0) {
      get_packeIdx++;
      let tempLen = 0;
      devRealData = [];

      for (let i = 12; i < msg.length - 3; i += tempLen) {
        let clienObj = { len: 0, oid: 0, value: 0 };

        clienObj.len = msg.readUInt8(i);
        clienObj.oid = msg.readUInt32LE(i + 1);
        tempLen = clienObj.len;
        if (clienObj.len === 6) clienObj.value = msg.readUInt8(i + 5);
        else if (clienObj.len === 7) clienObj.value = msg.readUInt16LE(i + 5);
        else if (clienObj.len === 9) clienObj.value = msg.readUInt32LE(i + 5);
        else clienObj.value = 0;
        devRealData.push(clienObj);
        clienObj = [];
      }
      //  console.log("devRealData="+JSON.stringify(devRealData));
    } else if (recvCmd === 0x82 && recvAnswer === 0) {
    //  console.log(devRealData);
    } else {
    }
    setCommTimeoutCnt(0);
  }
});

function Uint8ArrayToString(fileData) {
  var dataString = '';
  for (var i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData[i]);
  }
  return dataString;
}

// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt

/* utf.js - UTF-8 <=> UTF-16 convertion
 library is free.  You can redistribute it and/or modify it.
 */

function Utf8ArrayToStr(array) {
  var out, i, len, c;
  var char2, char3;

  out = '';
  len = array.length;
  i = 0;
  while (i < len) {
    c = array[i++];
    switch (c >> 4) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
        // 0xxxxxxx
        out += String.fromCharCode(c);
        break;
      case 12:
      case 13:
        // 110x xxxx   10xx xxxx
        char2 = array[i++];
        out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
        break;
      case 14:
        // 1110 xxxx  10xx xxxx  10xx xxxx
        char2 = array[i++];
        char3 = array[i++];
        out += String.fromCharCode(((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0));
        break;
    }
  }
  return out;
}

udpserver.on('listening', () => {
  const address = udpserver.address();
  console.log(`udpserverr listening ${address.address}:${address.port}`);
  console.log("devIP="+devIP_addr+"; devPort="+devIP_port);
});

udpserver.bind(2345);

var timeOver = 0;

const countTime = 10;
var get_packeIdx = 0;
function getAllDevTabDataFromDev() {
  if (++timeOver > countTime) timeOver = countTime;
  if (timeOver >= countTime) {
    //  console.log("devIP_addr="+devIP_addr);
    //  console.log("devIP_port="+devIP_port);

    timeOver = 0;
    if (get_packeIdx < udpRdData.length) {
      g_packetNum = get_packeIdx;
      let data = new dev_formPacket2Sent(0x81, udpRdData[get_packeIdx]);
      udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
    } else if (get_packeIdx == udpRdData.length) {
      let data = new dev_formPacket2Sent(0x80, null);
      udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
    } else {
      get_packeIdx = 0;
      clearInterval(getAllDevTabDataInterval);
    }
  }
}
function getSpecifyDevTabDataFromDev(msg) {
  setCommTimeoutCnt(10);
  get_packeIdx = getPkTIdx(msg.tabName);
  if (get_packeIdx != null) {
    g_packetNum = get_packeIdx;
    let data = new dev_formPacket2Sent(0x81, udpRdData[get_packeIdx]);
    udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
  }
}
var getAllDevTabDataInterval = setInterval(getAllDevTabDataFromDev, 100);

// var test1 = setInterval(test, 8000);
// function test()
// {
//   console.log("----------------------------------------------------------------------");
//  // getAllDevTabDataInterval = setInterval(getAllDevTabDataFromDev, 100);
//   let data = new dev_formPacket2Sent(0x80, null);
//   udpserver.send(data, 0, data.length, devIP_port, devIP_addr);

// }

function dev_formPacket2Sent(cmd, data) {
  // console.log("data="+data );
  let comPackeLen;
  if (data != null) {
    comPackeLen = 12 + data.length + 3;
  } else {
    comPackeLen = 12 + 3;
  }
  buffer = Buffer.alloc(comPackeLen);
  // buffer.fill(0);
  let i = 0;
  devSn = 0x12345678;
  devId = 0x0;

  buffer[i++] = 0x7e;
  buffer[i++] = comPackeLen - 6;
  buffer[i++] = (comPackeLen - 6) >> 8;

  buffer[i++] = g_packetNum;
  buffer[i++] = g_packetNum >> 8;

  buffer[i++] = devSn;
  buffer[i++] = devSn >> 8;
  buffer[i++] = devSn >> 16;
  buffer[i++] = devSn >> 24;

  buffer[i++] = devId;
  buffer[i++] = cmd;
  buffer[i++] = 0xff;
  if (data != null) {
    for (let j = 0; j < data.length; j++) {
      buffer[i++] = data[j];
    }
  }
  let temp = crcCheck(buffer, 3, comPackeLen - 6);
  buffer[i++] = temp>>8;
  buffer[i++] = temp ;
  buffer[i++] =0x7e;
  return buffer;
}
// function char2buf(str){
//   let out = new ArrayBuffer(str.length*2);
//   let u16a= new Uint16Array(out);
//   let strs = str.split("");
//   for(let i =0 ; i<strs.length;i++){
//       u16a[i]=strs[i].charCodeAt();
//   }
//   return out;
//   // console.log( toString.call(buffer) );
// }
function char2buf(str) {
  let out = new ArrayBuffer(str.length);
  let u16a = new Uint8Array(out);
  let strs = str.split('');
  // console.log('str=' + str);
  // console.log('strs=' + strs);
  for (let i = 0; i < strs.length; i++) {
    u16a[i] = strs[i].charCodeAt();
  }
  return out;
  //console.log( toString.call(buffer) );
}
function oidObj2hex(input) {
  var bytes = new Array();
  let temp =input[0] & 0xff;
  let len =temp;
  bytes.push(temp);
  temp =input[1] & 0xff;
  bytes.push(temp);
   temp =(input[1]>>8) & 0xff;
  bytes.push(temp);
  temp =(input[1]>>16) & 0xff;
  bytes.push(temp)
  temp =(input[1]>>24) & 0xff;
  bytes.push(temp)
  if(len>=6){
    temp =(input[2]) & 0xff;
    bytes.push(temp)
  } 
  if(len>=7){
    temp =(input[2]>>8) & 0xff;
    bytes.push(temp)
  } 
  if(len>=8){
    temp =(input[2]>>16) & 0xff;
    bytes.push(temp)
  } 
  if(len>=9){
    temp =(input[2]>>24) & 0xff;
    bytes.push(temp)
  } 
  return bytes;
}
function str2UTF8(str) {
  var bytes = new Array();
  var len, c;
  len = str.length;
  for (var i = 0; i < len; i++) {
    c = str.charCodeAt(i);
    if (c >= 0x010000 && c <= 0x10ffff) {
      bytes.push(((c >> 18) & 0x07) | 0xf0);
      bytes.push(((c >> 12) & 0x3f) | 0x80);
      bytes.push(((c >> 6) & 0x3f) | 0x80);
      bytes.push((c & 0x3f) | 0x80);
    } else if (c >= 0x000800 && c <= 0x00ffff) {
      bytes.push(((c >> 12) & 0x0f) | 0xe0);
      bytes.push(((c >> 6) & 0x3f) | 0x80);
      bytes.push((c & 0x3f) | 0x80);
    } else if (c >= 0x000080 && c <= 0x0007ff) {
      bytes.push(((c >> 6) & 0x1f) | 0xc0);
      bytes.push((c & 0x3f) | 0x80);
    } else {
      bytes.push(c & 0xff);
    }
  }
  return bytes;
}
function getPkTIdx(msg) {
  for (let i = 0; i < tabName.length; i++) {
    if (msg === tabName[i]) {
      return i;
    }
  }
  return null;
}


function cfgCom2Dev(msg) {
  //  console.log('msg=%o', msg);
  setCommTimeoutCnt(10);
 // let input = new Buffer();
 
  let cmd;
  let ctx=null;
  if(msg.cmd=="devReset")cmd=0x84;
  else if(msg.cmd=="kaizhanReport")cmd=0x83;
  else if(msg.cmd=="setValue"){
    ctx=oidObj2hex(msg.ctx);
    cmd=0x02;
  }
  else return;
  
  get_packeIdx = 0;
  g_packetNum = get_packeIdx;
  let data = dev_formPacket2Sent(cmd,ctx);
  udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
}

function updateDevTabData(msg) {
  // console.log('msg=%o', msg.data);
  setCommTimeoutCnt(10);
  get_packeIdx = getPkTIdx(msg.tabName);
  g_packetNum = get_packeIdx;
  let inputDataBuff = str2UTF8(msg.data);
  let data = dev_formPacket2Sent(0x82, inputDataBuff);
  udpserver.send(data, 0, data.length, devIP_port, devIP_addr);
}
function crcCheck(msg, startIdx, len) {
  let crc = Number(0xffff);
  for (let i = 0; i < len; i++) {
    crc = crc ^ msg[i + startIdx];
    for (let j = 0; j < 8; j++) {
      if ((crc & 0x00000001) != 0) {
        crc = (crc >> 1) ^ 0xa001;
      } else {
        crc >>= 1;
      }
      crc &= 0x0000ffff;
    }
  }
  return crc;
}
function getCommTimeoutCnt() {
  return g_commTimeoutCnt;
}
function setCommTimeoutCnt(data) {
  return (g_commTimeoutCnt = data);
}
exports.udpserver = udpserver;
exports.devTabData = devTabData;
exports.devRealData = devRealData;
exports.getDevRealData = getDevRealData;
exports.getDevTabData = getDevTabData;
exports.updateDevTabData = updateDevTabData;
exports.getCommTimeoutCnt = getCommTimeoutCnt;
exports.setCommTimeoutCnt = setCommTimeoutCnt;
exports.getSpecifyDevTabDataFromDev = getSpecifyDevTabDataFromDev;
exports.cfgCom2Dev = cfgCom2Dev;
exports.getDevRealDataComPacketSent = getDevRealDataComPacketSent;

